package de.justphil.tcg.tcgserver.rest.db.mapstores;

import static de.justphil.tcg.tcgserver.commons.logging.TCGLogging.restLogger;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.TypedQuery;

import org.slf4j.Logger;

import com.hazelcast.core.MapStore;

import de.justphil.tcg.tcgserver.commons.domain.Property;
import de.justphil.tcg.tcgserver.commons.management.Application;

public class PropertyMapStore implements MapStore<Long, Property> {

	private static final Logger log = restLogger(PropertyMapStore.class);
	
	private final EntityManagerFactory factory;

	public PropertyMapStore() {
		log.debug("New object created!");
		factory = Application.getEntityManagerFactory();
	}
	
	@Override
	public Property load(Long propertyId) {
		log.debug("load()");
		
		EntityManager em = factory.createEntityManager();
		Property property = em.find(Property.class, propertyId);
		em.close();
		
		return property;
	}

	@Override
	public Map<Long, Property> loadAll(Collection<Long> propertyIds) {
		log.debug("loadAll()");
		
		EntityManager em = factory.createEntityManager();
		Map<Long, Property> propertyMap = new HashMap<Long, Property>();
		
		List<Property> propertyList = getPropertyList(em);
		for(Property property : propertyList) {
			propertyMap.put(property.getId(), property);
		}
		
		em.close();
		
		return propertyMap;
	}

	@Override
	public Set<Long> loadAllKeys() {
		log.debug("loadAllKeys()");
		
		EntityManager em = factory.createEntityManager();
		
		Set<Long> propertyIds = new HashSet<Long>();
		
		List<Property> propertyList = getPropertyList(em);
		for (Property property : propertyList) {
			propertyIds.add(property.getId());
		}
		
		em.close();
		
		return propertyIds;
	}
	
	private List<Property> getPropertyList(EntityManager em) {
		TypedQuery<Property> q = em.createQuery("SELECT p FROM Property p ORDER BY p.id", Property.class);
		return q.getResultList();
	}

	@Override
	public void delete(Long propertyId) {
		log.debug("delete()");
		
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		
		Property property = em.find(Property.class, propertyId);
		if (property != null) {
			em.remove(property);
		}
		
		em.getTransaction().commit();
		em.close();
	}

	@Override
	public void deleteAll(Collection<Long> propertyIds) {
		log.debug("deleteAll()");
		
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		
		Property property = null;
		for (Long propertyId : propertyIds) {
			property = em.find(Property.class, propertyId);
			if (property != null) {
				em.remove(property);
			}
		}
		
		em.getTransaction().commit();
		em.close();
	}

	@Override
	public void store(Long propertyId, Property property) {
		log.debug("store()");
		
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		
		Property pProperty = em.find(Property.class, propertyId);
		if (pProperty == null) {
			log.debug("em.persist()");
			em.persist(property);
		}
		else {
			log.debug("em.merge()");
			em.merge(property);
		}
		
		em.getTransaction().commit();
		em.close();
	}

	@Override
	public void storeAll(Map<Long, Property> propertyMap) {
		log.debug("storeAll()");
		
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		
		Property pProperty	= null;
		Property property	= null;
		for (Long propertyId : propertyMap.keySet()) {
			property = propertyMap.get(propertyId);
			
			pProperty = em.find(Property.class, propertyId);
			if (pProperty == null) {
				log.debug("em.persist()");
				em.persist(property);
			}
			else {
				log.debug("em.merge()");
				em.merge(property);
			}
		}
		
		em.getTransaction().commit();
		em.close();
	}

}
